use actix_web::web;
use actix_web::web::ServiceConfig;
use utoipa::{Modify, OpenApi};
use utoipa::openapi::security::{Http, HttpAuthScheme, SecurityScheme};
use crate::handler::{role_handler, public_handler, user_handler};
use crate::middleware::auth_middleware::JwtAuth;

/// 定义API文档
///
/// @author 张翔宇
/// @since 2025年7月3日
#[derive(OpenApi)]
#[openapi(
    // 没法方法名称保证全局唯一，不然swagger请求地址会被相同的覆盖
    paths(
        crate::handler::public_handler::hash_password,
        crate::handler::public_handler::login,
        crate::handler::role_handler::role_add,
        crate::handler::role_handler::role_info,
        crate::handler::role_handler::role_page,
        crate::handler::user_handler::user_add,
        crate::handler::user_handler::user_info,
        crate::handler::user_handler::user_page,
        crate::handler::user_handler::user_modify_status,
        crate::handler::user_handler::user_delete,
    ),
    info(
        title = "天命 API 接口",
        version = "1.0.0",
        description = "提供天命后台管理系统功能的 REST API",
        contact(
            name = "技术支持",
            email = "zhang.xiangyu@foxmail.com",
            url = "https://blog.meatball.org.cn"
        ),
        license(
            name = "Apache 2.0",
            url = "https://www.apache.org/licenses/LICENSE-2.0.html"
        )
    ),
    modifiers(&SecurityAddon),
    security(
        ("BEARER_AUTH" = [])
    )
)]
pub struct ApiDoc;

struct SecurityAddon;

/// 为SecurityAddon实现utoipa的Modify trait，用于向OpenAPI文档添加安全认证方案
impl Modify for SecurityAddon {

    /// 实现Modify trait的核心方法，用于修改OpenAPI文档结构
    /// 
    /// 该方法会向OpenAPI文档的components中添加一个Bearer JWT认证方案，
    /// 供API文档中需要认证的接口引用
    /// 
    /// # 参数
    /// * `&self` - 当前SecurityAddon实例的不可变引用
    /// * `openapi` - OpenApi文档对象的可变引用，用于修改文档内容
    fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
        if let Some(components) = openapi.components.as_mut() {
            components.add_security_scheme(
                "BEARER_AUTH",
                SecurityScheme::Http(
                    Http::builder()
                        .scheme(HttpAuthScheme::Bearer)
                        .bearer_format("JWT")
                        .description(Some("在输入框中输入你的令牌"))
                        .build()
                )
            );
        }
    }
}

/// 创建并配置应用的路由规则
/// 
/// 该函数用于定义API的路由结构，包括公开接口和需要认证的接口，
/// 通过配置路由作用域和中间件来管理接口访问权限
/// 
/// # 参数
/// * `cfg` - 服务配置对象的可变引用，用于注册路由规则
pub fn create_router(cfg: &mut ServiceConfig) {
    // 路由
    let public_routes = web::scope("/api")
        .service(
            // 公开的
            web::scope("/public")
                .service(public_handler::hash_password)
                .service(public_handler::login)
        )
        .service(
            web::scope("/role")
                .wrap(JwtAuth)
                .service(role_handler::role_add)
                .service(role_handler::role_info)
                .service(role_handler::role_page)
        )
        .service(
            web::scope("/user")
                .wrap(JwtAuth)
                .service(user_handler::user_add)
                .service(user_handler::user_info)
                .service(user_handler::user_page)
                .service(user_handler::user_modify_status)
                .service(user_handler::user_delete)
        );

    cfg.service(public_routes);
}